﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;

namespace RainwaterTankEstimator
{
    class Estimator
    {
        #region Properties

        public int RoofArea
        {
            get;
            private set;
        }

        public int TankSize
        {
            get;
            private set;
        }

        public int WaterUse
        {
            get;
            private set;
        }

        public int FirstFlush
        {
            get;
            private set;
        }

        public float Efficiency
        {
            get;
            private set;
        }

        public float WaterLevel
        {
            get;
            private set;
        }

        public List<MonthDataViewModel> Months
        {
            get;
            private set;
        }

        public List<float> DemandMet
        {
            get;
            private set;
        }

        public ObservableCollection<Datum> Jan
        {
            get
            {
                return this.Months[0].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Feb
        {
            get
            {
                return this.Months[1].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Mar
        {
            get
            {
                return this.Months[2].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Apr
        {
            get
            {
                return this.Months[3].AdjustedData;
            }
        }

        public ObservableCollection<Datum> May
        {
            get
            {
                return this.Months[4].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Jun
        {
            get
            {
                return this.Months[5].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Jul
        {
            get
            {
                return this.Months[6].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Aug
        {
            get
            {
                return this.Months[7].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Sep
        {
            get
            {
                return this.Months[8].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Oct
        {
            get
            {
                return this.Months[9].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Nov
        {
            get
            {
                return this.Months[10].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Dec
        {
            get
            {
                return this.Months[11].AdjustedData;
            }
        }

        public ObservableCollection<Datum> Jan2
        {
            get
            {
                return this.Months[0].DemandData;
            }
        }

        public ObservableCollection<Datum> Feb2
        {
            get
            {
                return this.Months[1].DemandData;
            }
        }

        public ObservableCollection<Datum> Mar2
        {
            get
            {
                return this.Months[2].DemandData;
            }
        }

        public ObservableCollection<Datum> Apr2
        {
            get
            {
                return this.Months[3].DemandData;
            }
        }

        public ObservableCollection<Datum> May2
        {
            get
            {
                return this.Months[4].DemandData;
            }
        }

        public ObservableCollection<Datum> Jun2
        {
            get
            {
                return this.Months[5].DemandData;
            }
        }

        public ObservableCollection<Datum> Jul2
        {
            get
            {
                return this.Months[6].DemandData;
            }
        }

        public ObservableCollection<Datum> Aug2
        {
            get
            {
                return this.Months[7].DemandData;
            }
        }

        public ObservableCollection<Datum> Sep2
        {
            get
            {
                return this.Months[8].DemandData;
            }
        }

        public ObservableCollection<Datum> Oct2
        {
            get
            {
                return this.Months[9].DemandData;
            }
        }

        public ObservableCollection<Datum> Nov2
        {
            get
            {
                return this.Months[10].DemandData;
            }
        }

        public ObservableCollection<Datum> Dec2
        {
            get
            {
                return this.Months[11].DemandData;
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        public Estimator(int roofArea, int tankSize, int waterUse, int firstFlush, float efficiency)
        {
            this.RoofArea = roofArea;
            this.TankSize = (int)(tankSize * 3.785);
            this.WaterUse = waterUse;
            this.FirstFlush = firstFlush;
            this.Efficiency = efficiency;
            this.WaterLevel = 0;
            this.Months = new List<MonthDataViewModel>();
            this.DemandMet = new List<float>();

            for (int i = 1; i < 13; i++)
            {
                this.Months.Add(new MonthDataViewModel(i));
            }
        }

        #endregion

        /// <summary>
        /// Read the data
        /// </summary>
        public void ReadFile(string file)
        {
            // Read file
            using (var s = new StreamReader(file))
            {
                string line;

                while ((line = s.ReadLine()) != null)
                {
                    // Parse entry
                    string[] entry = line.Split(new char[] { ',', '-' });

                    // Get month
                    int month = Convert.ToInt32(entry[1]);

                    // Get retained water
                    float rain = Convert.ToSingle(entry[3]);
                    var actualRain = rain * this.Efficiency;
                    var loss = rain - actualRain;

                    // First flush
                    var flushAmount = actualRain > this.FirstFlush ? this.FirstFlush : actualRain;
                    actualRain -= flushAmount;

                    // Add to tank
                    this.WaterLevel += (actualRain * this.RoofArea);
                    var fillLevel = actualRain * this.RoofArea;
                    var overflow = this.WaterLevel > this.TankSize ? this.WaterLevel - this.TankSize : 0;

                    if (overflow > 0)
                    {
                        this.WaterLevel = this.TankSize;
                        fillLevel -= overflow;
                    }

                    this.DemandMet.Add((float)this.WaterLevel / (float)this.WaterUse);
                    this.WaterLevel = this.WaterLevel > this.WaterUse ? this.WaterLevel - this.WaterUse : 0;

                    this.Months[month - 1].AddData(loss * this.RoofArea, flushAmount * this.RoofArea, overflow, fillLevel, (int)this.WaterLevel / this.TankSize, (float)this.WaterLevel / (float)this.WaterUse);
                }
            }
        }
    }
}
